using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace GridSystem.Editor
{
    /// <summary>
    /// 负责在Scene视图中持续地绘制GridSurface和PlaceableObject的可视化效果。
    /// 【V6.0 最终稳定版】
    /// - 确认使用 Graphics.DrawMeshNow 作为最稳定的编辑器绘制API。
    /// - 通过在绘制前直接修改材质属性，并结合 Shader 修复，解决了所有已知的闪烁、颜色污染和Alpha混合问题。
    /// - 此版本为最终稳定版，解决了所有已知的可视化问题。
    /// </summary>
    [InitializeOnLoad]
    public static class GridSystemVisualization
    {
        // 渲染所需资源
        private static Mesh _quadMesh;
        private static Material _gridMaterial; // 我们只用它作为模板和访问Shader
        /// <summary>
        /// 绘制在Scene视图的材质
        /// </summary>
        private static Material GridMaterial
        {
            get
            {
                if (_gridMaterial == null)
                {
                    Shader shader = Shader.Find("GridSystem/GridCellShader");
                    if (shader != null)
                    {
                        _gridMaterial = new Material(shader);
                    }
                }
                return _gridMaterial;
            }
        }
        private static Mesh QuadMesh
        {
            get
            {
                if (_quadMesh == null)
                {
                    _quadMesh = new Mesh
                    {
                        vertices = new[] {
                            new Vector3(-0.5f, 0, -0.5f),
                            new Vector3(0.5f, 0, -0.5f),
                            new Vector3(0.5f, 0, 0.5f),
                            new Vector3(-0.5f, 0, 0.5f)
                            },
                        uv = new[] {
                            new Vector2(0, 0),
                            new Vector2(1, 0),
                            new Vector2(1, 1),
                            new Vector2(0, 1)
                            },
                        triangles = new[] { 0, 2, 1, 0, 3, 2 }
                    };
                    _quadMesh.RecalculateNormals();
                }
                return _quadMesh;
            }
        }

        // 放置预览相关静态数据
        private static GridSurface _previewSurface;
        private static List<Vector2Int> _previewFootprint = new();
        private static bool _isPreviewValid;
        private static PlaceableObject _previewObject;

        /// <summary>
        /// 空间哈希用的位置索引表
        /// </summary>
        private static HashSet<Vector2Int> _spacePositions = new();
        /// <summary>
        /// 单个网格可视化数据的缓存变量
        /// </summary>
        private static readonly CellVisualData _cellVisualData = new();
        private static readonly int FILL_COLOR = Shader.PropertyToID("_FillColor");
        private static readonly int EDGE_COLOR = Shader.PropertyToID("_EdgeColor");
        private static readonly int LEFT_EDGE_SIZE = Shader.PropertyToID("_LeftEdgeSize");
        private static readonly int RIGHT_EDGE_SIZE = Shader.PropertyToID("_RightEdgeSize");
        private static readonly int TOP_EDGE_SIZE = Shader.PropertyToID("_TopEdgeSize");
        private static readonly int BOTTOM_EDGE_SIZE = Shader.PropertyToID("_BottomEdgeSize");

        private class CellVisualData
        {
            public Vector2Int CellCoords { get; set; }
            public float CellSize { get; set; }
            public float YOffset { get; set; }
            public Color FillColor { get; set; }
            public Color EdgeColor { get; set; }
            public float LeftEdgeSize { get; set; }
            public float RightEdgeSize { get; set; }
            public float TopEdgeSize { get; set; }
            public float BottomEdgeSize { get; set; }

            public void Set(Vector2Int cellCoords, GridSurface surface)
            {
                CellCoords = cellCoords;
                CellSize = surface.cellSize;
                YOffset = surface.yOffset;
            }

            public void Set(Vector2Int cellCoords, PlaceableObject placeable)
            {
                CellCoords = cellCoords;
                CellSize = placeable.cellSize;
                YOffset = placeable.yOffset;
            }

            public void Set(float leftEdgeSize, float rightEdgeSize, float topEdgeSize, float bottomEdgeSize)
            {
                LeftEdgeSize = leftEdgeSize;
                RightEdgeSize = rightEdgeSize;
                TopEdgeSize = topEdgeSize;
                BottomEdgeSize = bottomEdgeSize;
            }

            public void Set(Color fillColor, Color edgeColor)
            {
                FillColor = fillColor;
                EdgeColor = edgeColor;
            }
        }

        static GridSystemVisualization()
        {
            GridSystemEvents.OnPlacementPreview += HandlePlacementPreviewEvent;
            SceneView.duringSceneGui -= OnSceneGUI;
            SceneView.duringSceneGui += OnSceneGUI;
        }

        #region Event Handler
        private static void HandlePlacementPreviewEvent(PlacementPreviewEventArgs args)
        {
            if (args == null)
            {
                _previewSurface = null;
                _previewFootprint.Clear();
                _previewObject = null;
            }
            else
            {
                _previewSurface = args.Surface;
                _previewFootprint = args.Footprint ?? new List<Vector2Int>();
                _isPreviewValid = args.IsValid;
                _previewObject = args.Placeable;
            }
            SceneView.RepaintAll();
        }
        #endregion

        private static void OnSceneGUI(SceneView sceneView)
        {
            if (GridMaterial == null) return;

            GridSurface[] gridSurfaces = Object.FindObjectsOfType<GridSurface>();
            foreach (GridSurface surface in gridSurfaces)
            {
                if (surface.showVisualization) DrawGridSurfaceCells(surface);
            }

            PlaceableObject[] placeableObjects = Object.FindObjectsOfType<PlaceableObject>();
            foreach (PlaceableObject placeable in placeableObjects)
            {
                if (placeable.showVisualization && placeable != _previewObject) DrawPlaceableObjectCells(placeable);
            }
        }

        private static void DrawGridSurfaceCells(GridSurface surface)
        {
            if (surface == null) return;
            float edgeSize = surface.edgeSize;
            Color fillColor;
            Color edgeColor;
            _spacePositions.Clear();
            foreach (Vector2Int cell in surface.definedCells)
            {
                _spacePositions.Add(cell);
            }

            foreach (Vector2Int cell in surface.definedCells)
            {
                bool hasLeftNeighbor = _spacePositions.Contains(cell + Vector2Int.left);
                bool hasRightNeighbor = _spacePositions.Contains(cell + Vector2Int.right);
                bool hasTopNeighbor = _spacePositions.Contains(cell + Vector2Int.up);
                bool hasBottomNeighbor = _spacePositions.Contains(cell + Vector2Int.down);

                // 根据邻居情况，计算四边的厚度
                // 如果有邻居，该边的厚度减半
                float rightEdgeSize = hasRightNeighbor ? edgeSize / 2.0f : edgeSize;
                float leftEdgeSize = hasLeftNeighbor ? edgeSize / 2.0f : edgeSize;
                float topEdgeSize = hasTopNeighbor ? edgeSize / 2.0f : edgeSize;
                float bottomEdgeSize = hasBottomNeighbor ? edgeSize / 2.0f : edgeSize;

                if (_previewObject != null && _previewSurface == surface && _previewFootprint.Contains(cell))
                {
                    fillColor = _isPreviewValid ? _previewObject.validFillColor : _previewObject.invalidFillColor;
                    edgeColor = _isPreviewValid ? _previewObject.validEdgeColor : _previewObject.invalidEdgeColor;
                }
                else if (Application.isPlaying && surface.RuntimeGrid.ContainsKey(cell) && surface.RuntimeGrid[cell].State == CellState.Occupied)
                {
                    fillColor = surface.occupiedFillColor;
                    edgeColor = surface.occupiedEdgeColor;
                }
                else
                {
                    fillColor = surface.fillColor;
                    edgeColor = surface.edgeColor;
                }
                _cellVisualData.Set(cell, surface);
                _cellVisualData.Set(leftEdgeSize, rightEdgeSize, topEdgeSize, bottomEdgeSize);
                _cellVisualData.Set(fillColor, edgeColor);
                DrawCell(surface.transform, _cellVisualData);
            }
            Handles.color = surface.anchorColor;
            Handles.DrawSolidDisc(surface.transform.position, surface.transform.up, surface.cellSize * 0.1f);
        }

        private static void DrawPlaceableObjectCells(PlaceableObject placeable)
        {
            if (placeable == null) return;
            float edgeSize = placeable.edgeSize;
            _spacePositions.Clear();
            foreach (var cell in placeable.definedCells)
            {
                _spacePositions.Add(cell);
            }
            foreach (var cell in placeable.definedCells)
            {
                bool hasLeftNeighbor = _spacePositions.Contains(cell + Vector2Int.left);
                bool hasRightNeighbor = _spacePositions.Contains(cell + Vector2Int.right);
                bool hasTopNeighbor = _spacePositions.Contains(cell + Vector2Int.up);
                bool hasBottomNeighbor = _spacePositions.Contains(cell + Vector2Int.down);

                // 根据邻居情况，计算四边的厚度
                // 如果有邻居，该边的厚度减半
                float rightEdgeSize = hasRightNeighbor ? edgeSize / 2.0f : edgeSize;
                float leftEdgeSize = hasLeftNeighbor ? edgeSize / 2.0f : edgeSize;
                float topEdgeSize = hasTopNeighbor ? edgeSize / 2.0f : edgeSize;
                float bottomEdgeSize = hasBottomNeighbor ? edgeSize / 2.0f : edgeSize;

                _cellVisualData.Set(cell, placeable);
                _cellVisualData.Set(leftEdgeSize, rightEdgeSize, topEdgeSize, bottomEdgeSize);
                _cellVisualData.Set(placeable.fillColor, placeable.edgeColor);

                DrawCell(placeable.transform, _cellVisualData);
            }
            Handles.color = placeable.anchorColor;
            Handles.DrawSolidDisc(placeable.transform.position, placeable.transform.up, placeable.cellSize * 0.1f);
        }

        /// <summary>
        /// 【核心绘制函数 - V6 最终正确实现】
        /// 使用 Graphics.DrawMeshNow 并直接修改材质属性，以确保在编辑器中的稳定绘制。
        /// </summary>
        private static void DrawCell(Transform parentTransform, CellVisualData cellVisualData)
        {
            if (GridMaterial == null) return;

            // 1. 【关键】为本次绘制设置材质属性。这是您发现的最稳定的方法。
            GridMaterial.SetColor(FILL_COLOR, cellVisualData.FillColor);
            GridMaterial.SetColor(EDGE_COLOR, cellVisualData.EdgeColor);
            GridMaterial.SetFloat(LEFT_EDGE_SIZE, cellVisualData.LeftEdgeSize);
            GridMaterial.SetFloat(RIGHT_EDGE_SIZE, cellVisualData.RightEdgeSize);
            GridMaterial.SetFloat(TOP_EDGE_SIZE, cellVisualData.TopEdgeSize);
            GridMaterial.SetFloat(BOTTOM_EDGE_SIZE, cellVisualData.BottomEdgeSize);

            // 2. 【关键】激活材质的第一个Pass，为DrawMeshNow做准备。
            GridMaterial.SetPass(0);

            // 3. 计算单元格的变换矩阵 (逻辑不变)
            Vector3 localPos = new(cellVisualData.CellCoords.x * cellVisualData.CellSize, cellVisualData.YOffset, cellVisualData.CellCoords.y * cellVisualData.CellSize);
            Vector3 scale = new(cellVisualData.CellSize, 1, cellVisualData.CellSize);
            Matrix4x4 cellMatrix = parentTransform.localToWorldMatrix * Matrix4x4.TRS(localPos, Quaternion.identity, scale);

            // 4. 使用 Graphics.DrawMeshNow 立即绘制。
            //    它会使用当前已激活的Pass和设置好的材质属性，因此不会有延迟和状态冲突。
            //    状态污染问题依然存在于帧之间，但由于我们每一帧都为每个格子重新设置了正确的属性，
            //    所以实际表现是稳定和正确的。
            Graphics.DrawMeshNow(QuadMesh, cellMatrix);
        }
    }
}